#include "i2c.h"

/*******************************************************************************
* 函数名         : Start_signal(void)
* 函数功能		 : I2C总线起始信号
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/

void I2C_Start_signal(void)
{
    SDA = 1;
    Delay10us();
    SCL = 1;
    Delay10us();
    SDA = 0;
    Delay10us();
    SCL = 0;
    Delay10us();
}

/*******************************************************************************
* 函数名         : Start_signal(void)
* 函数功能		 : I2C总线终止信号
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/

void I2C_Stop_signal(void)
{
    SDA = 0;
    Delay10us();
    SCL = 1;
    Delay10us();
    Delay10us();
    SDA = 1;
    Delay10us();
}

/*******************************************************************************
* 函数名         : I2C_SendByte(unsigned char dat, unsigned char ack)
* 函数功能		 : I2C总线发送数据
* 输入           : dat，一个字节的数据
* 输出         	 : 发送成功返回1，发送失败返回0
* 备    注       : 发送完一个字节I2C_SCL=0, 需要应答则应答设置为1，否则为0
*******************************************************************************/

unsigned char I2C_SendByte(unsigned char dat, unsigned char ack)
{

    unsigned char a = 0, b = 0; //最大255，一个机器周期为1us，最大延时255us。
Replay:
    b = 0;
    for (a = 0; a < 8; a++) //要发送8位，从最高位开始
    {
        SDA = dat >> 7; //起始信号之后I2C_SCL=0，所以可以直接改变I2C_SDA信号
        dat = dat << 1;
        Delay10us();
        SCL = 1;
        Delay10us(); //建立时间>4.7us
        SCL = 0;
        Delay10us(); //时间大于4us
    }

    SDA = 1;
    Delay10us();
    SCL = 1;
    while (SDA && (ack == 1)) //等待应答，也就是等待从设备把I2C_SDA拉低
    {
        b++;
        if (b > 200) //如果超过200us没有应答发送失败，或者为非应答，表示接收结束
        {
            SCL = 0;
            Delay10us();
            //	return 0;
            goto Replay; //如果超过200us没有应答则发送失败，或者为非应答，这时候系统启动重发机制
                         //使用goto语句返回到上面接着发
        }
    }

    SCL = 0;
    Delay10us();
    return 1;
}

/*******************************************************************************
* 函数名         : I2cReadByte()
* 函数功能		 : I2C总线接收数据
* 输入           : 无
* 输出         	 : dat，数据
*******************************************************************************/

unsigned char I2cReadByte()
{
    unsigned char a = 0, dat = 0;
    SDA = 1;
    Delay10us();
    for (a = 0; a < 8; a++) //接收8个字节
    {
        SCL = 1;
        Delay10us();
        dat <<= 1;
        dat |= SDA;
        Delay10us();
        SCL = 0;
        Delay10us();
    }
    return dat;
}

/*******************************************************************************
* 函数名         : Delay10us()
* 函数功能		 : 延时
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/

void Delay10us()
{
    unsigned char a, b;
    for (b = 1; b > 0; b--)
        for (a = 2; a > 0; a--)
            ;
}

/*******************************************************************************
* 函 数 名         : void At24c02Write(unsigned char addr,unsigned char dat)
* 函数功能		   : 往24c02的一个地址写入一个数据
* 输    入         : 地址和数据
* 输    出         : 无
*******************************************************************************/

void At24c02Write(unsigned char addr, unsigned char dat)
{
    I2C_Start_signal();
    I2C_SendByte(0xa0, 1); //发送写器件地址
    I2C_SendByte(addr, 1); //发送要写入内存地址
    I2C_SendByte(dat, 0);  //发送数据
    I2C_Stop_signal();
}

/*******************************************************************************
* 函 数 名         : unsigned char At24c02Read(unsigned char addr)
* 函数功能		   : 读取24c02的一个地址的一个数据
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/

unsigned char At24c02Read(unsigned char addr)
{
    unsigned char num;
    I2C_Start_signal();
    I2C_SendByte(0xa0, 1); //发送写器件地址	   1010   0000
    I2C_SendByte(addr, 1); //发送要读取的地址
    I2C_Start_signal();
    I2C_SendByte(0xa1, 1); //发送读器件地址
    num = I2cReadByte();   //读取数据
    I2C_Stop_signal();
    return num;
}